package net.cyndeline.scalarlib.rldungeon.grammar

import scalax.collection.immutable.Graph
import scalax.collection.GraphEdge.UnDiEdge
import net.cyndeline.scalarlib.rldungeon.grammar.util.Morphism
import net.cyndeline.scalarlib.rldungeon.dgs.graph.{DGSFunctionality, Room}
import scalax.collection.GraphPredef.OuterEdge

/**
 * Represents the right-hand side of a production rule, and modifies a graph based on a morphism.
 */
trait ComponentProduction[VType <: Room[VType], EType[X] <: UnDiEdge[X] with DGSFunctionality[X, EType] with OuterEdge[X, EType]] {

  /**
   * Performs a modification of a graph.
   *
   * @param morphism Maps a set of vertices in a production pattern to the vertices in the sub graph. It's up to the
   *                 ComponentProductions implementation to know which vertices to use as keys here.
   * @param totalGraph The graph that the sub graph appears in, in its entirety. Every vertex here is not guaranteed to
   *                   appear in the morphism. This graph is only supplied to allow ComponentProductions to perform
   *                   graph-spanning algorithms that doesn't rely on a particular pattern, as well as giving them the
   *                   graph as it appears before modification.
   *                   NOTE: Do not use this graph to check if the graph is valid for a particular modification, put
   *                   those checks in the negative condition inside the Production.
   * @return a graph modified by this production.
   */
  def apply(morphism: Morphism[VType], totalGraph: Graph[VType, EType]): Graph[VType, EType]

}
